package com.iwhalecloud.bss.kite.cucc.common.util;

import com.iwhalecloud.bss.kite.common.constant.ErrorConsts;
import com.iwhalecloud.bss.kite.common.util.KiteStringUtils;
import com.iwhalecloud.bss.kite.cucc.client.annotation.CuccAnnotation;
import com.ztesoft.zsmart.core.log.ZSmartLogger;
import org.springframework.dao.support.DataAccessUtils;

import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
import java.util.regex.Pattern;

public class DateUtils {
    private static final ZSmartLogger LOGGER = ZSmartLogger.getLogger(DateUtils.class);

    public static final String DATE_FORMAT = "yyyy-MM-dd";

    public static final String DEFAULT_PATTERN = "yyyy-MM-dd HH:mm:ss";

    public static final String LONG_PATTERN = "yyyyMMddHHmmss";

    public static final String DAY_PATTERN = "yyyyMMdd";

    public static final String MONTHPATTERN = "yyyy-MM";

    public static final String SECOND = ":00";

    public static final int TRUNCTO_YEAR = 0;

    public static final int TRUNCTO_MONTH = 1;

    public static final int TRUNCTO_DAY = 2;

    private static final String DATE_TIME_FORMAT_ONE = "[0-9]{4}-[0-1]?[0-9]{1}-[0-3]?[0-9]{1}T[0-5]?[0-9]{1}:[0-5]?[0-9]{1}:[0-5]?[0-9]{1}";

    private static final String DATE_TIME_FORMAT_TWO = "[0-9]{4}-[0-1]?[0-9]{1}-[0-3]?[0-9]{1}T[0-5]?[0-9]{1}:[0-5]?[0-9]{1}";

    private static final String DATE_TIME_FORMAT_NO_CHANGE = "[0-9]{4}-[0-1]?[0-9]{1}-[0-3]?[0-9]{1} [0-5]?[0-9]{1}:[0-5]?[0-9]{1}:[0-5]?[0-9]{1}";

    public static String getEndOfThisMonth() {
        Calendar calendar = Calendar.getInstance();

        calendar.set(5, calendar.getActualMaximum(5));
        DateFormat format = new SimpleDateFormat("yyyy-MM-dd 23:59:59");
        return format.format(calendar.getTime());
    }

    public static String getStartTimeOfNextMonth(String dateStr, String format) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        try {
            java.util.Date date = sdf.parse(dateStr);
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            calendar.set(5, 1);
            calendar.add(2, 1);
            calendar.set(10, 0);
            calendar.set(12, 0);
            calendar.set(13, 0);
            return sdf.format(calendar.getTime());
        }
        catch (ParseException e) {
            LOGGER.error(e.getMessage());
        }
        return null;
    }

    public static String plusDay(int num, String newDate) throws ParseException {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        java.util.Date currdate = format.parse(newDate);
        System.out.println("当前是:" + currdate);
        Calendar c = Calendar.getInstance();
        c.setTime(currdate);
        c.add(5, 1);

        String tomorrow = format.format(c.getTime());
        System.out.println("明天是:" + tomorrow);

        return tomorrow;
    }

    public static String current(String pattern) {
        return formatDate(current(), pattern);
    }

    public static java.util.Date current() {
        return new java.sql.Date(System.currentTimeMillis());
    }

    public static java.util.Date currentDate() {
        java.sql.Date date = new java.sql.Date(System.currentTimeMillis());
        return date;
    }

    public static Timestamp currentTime() {
        return new Timestamp(System.currentTimeMillis());
    }

    public static Timestamp addDay(Timestamp time, int days) {
        Calendar c = Calendar.getInstance();
        c.setTimeInMillis(time.getTime());
        c.add(6, days);
        return new Timestamp(c.getTimeInMillis());
    }

    public static Timestamp addDay(java.util.Date time, int days) {
        Calendar c = Calendar.getInstance();
        c.setTimeInMillis(time.getTime());
        c.add(6, days);
        return new Timestamp(c.getTimeInMillis());
    }

    public static Timestamp trunc(Timestamp time, int truncTo) {
        Calendar c = Calendar.getInstance();
        c.setTimeInMillis(time.getTime());
        int year = 0;
        int month = 0;
        int date = 1;
        int hour = 0;
        int minute = 0;
        int second = 0;
        if (truncTo >= 0) {
            year = c.get(1);
        }
        if (truncTo >= 1) {
            month = c.get(2);
        }
        if (truncTo >= 2) {
            date = c.get(5);
        }
        c.set(year, month, date, hour, minute, second);
        c.set(14, 0);
        return new Timestamp(c.getTimeInMillis());
    }

    public static void main(String[] args) {
        String day = current("dd");

        SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");
        System.out.println(getMonthString());
    }

    public static String strToDateLong(String strDate) {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");
        ParsePosition pos = new ParsePosition(0);
        java.util.Date strtodate = formatter.parse(strDate, pos);
        formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return formatter.format(strtodate);
    }

    public static java.sql.Date addDay(java.sql.Date date, int days) {
        Calendar c = Calendar.getInstance();
        c.setTimeInMillis(date.getTime());
        c.add(6, days);
        return new java.sql.Date(c.getTimeInMillis());
    }

    public static java.util.Date add(java.util.Date date, int filed, int amount) {
        Calendar c = Calendar.getInstance();
        c.setTimeInMillis(date.getTime());
        c.add(filed, amount);
        return new java.util.Date(c.getTimeInMillis());
    }

    public static Calendar toCalander(Timestamp timestamp) {
        /* 166 */
        Calendar c = Calendar.getInstance();
        /* 167 */
        c.setTimeInMillis(timestamp.getTime());
        /* 168 */
        return c;
    }

    /* 171 */
    public static Calendar toCalander(java.util.Date date) {
        Calendar c = Calendar.getInstance();
        /* 172 */
        c.setTimeInMillis(date.getTime());
        /* 173 */
        return c;
    }

    public static String formatDate(java.util.Date date) {
        /* 181 */
        return formatDate(date, "yyyy-MM-dd HH:mm:ss");
    }

    public static String formatDate(java.util.Date date, String pattern) {
        if (date == null)/* 186 */
        { return null; }
        if (pattern == null) {
            throw new IllegalArgumentException("pattern is null");
        }
        SimpleDateFormat formatter = new SimpleDateFormat(pattern);
        return formatter.format(date);
    }

    public static java.util.Date parse(String dateStr, Class resultClass) throws ParseException {
        return parse(dateStr, "yyyy-MM-dd HH:mm:ss", resultClass);
    }

    public static java.util.Date parseAsDate(String dateStr) {
        return parse(dateStr, "yyyy-MM-dd HH:mm:ss", java.sql.Date.class);
    }

    public static java.util.Date parseAsDate(String dateStr, String pattern) {
        return parse(dateStr, pattern, java.sql.Date.class);
    }

    public static java.util.Date parseAsTimestamp(String dateStr) {
        return parse(dateStr, "yyyy-MM-dd HH:mm:ss", Timestamp.class);
    }

    public static java.util.Date parse(String dateStr, String pattern, Class resultClass) {
        if (dateStr == null)/* 211 */
        {    throw new IllegalArgumentException("dateStr is null"); }
        if (pattern == null) {
            throw new IllegalArgumentException("pattern is null");
        }
        java.util.Date date;
        SimpleDateFormat formatter = new SimpleDateFormat(pattern);
        try {
            date = formatter.parse(dateStr);
        }
        catch (ParseException e) {
            throw new RuntimeException(e);
        }

        if (resultClass == null)/* 224 */
        {    return date; }
        if (resultClass.equals(java.sql.Date.class))/* 226 */
        {    return new java.sql.Date(date.getTime()); }
        if (resultClass.equals(Timestamp.class)) {
            return new Timestamp(date.getTime());
        }
        throw new IllegalArgumentException("result class must be java.sql.Date or java.sql.Timestamp");
    }

    public static java.util.Date addMonth(int amount) {
        return add(currentTime(), 2, amount);
    }

    public static java.util.Date addMonth(java.util.Date date, int amount) {
        return add(date, 2, amount);
    }

    public static java.util.Date addYear(java.util.Date date, int amount) {
        return add(date, 1, amount);
    }

    public static int getDay() {
        return Calendar.getInstance().get(5);
    }

    public static int getHour() {
        return Calendar.getInstance().get(11);
    }

    public static synchronized java.util.Date parseStrToDateTime(String dateStr) throws Exception {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return df.parse(dateStr);
    }

    /**
     * add by ma.junjun
     * 2021-08-27
     * 增加yyyy-MM格式输出
     * @return
     */
    public static synchronized String getMonthString() {
        /* 269 */
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
        /* 270 */
        return sdf.format(new java.util.Date());
    }


    public static synchronized String getDateString() {
        /* 269 */
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        /* 270 */
        return sdf.format(new java.util.Date(System.currentTimeMillis()));
    }

    public static synchronized String getDateString(java.util.Date date) {
        /* 274 */
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        /* 275 */
        return sdf.format(date);
    }

    public static synchronized java.util.Date parseStrToDate(String dateStr, String formater) throws Exception {
        /* 280 */
        SimpleDateFormat df = new SimpleDateFormat(formater);
        /* 281 */
        return df.parse(dateStr);
    }

    public static synchronized String getDateTimeString(java.util.Date date, String formater) {
        /* 286 */
        SimpleDateFormat sdf = new SimpleDateFormat(formater);
        /* 287 */
        return sdf.format(date);
    }

    public static String getAppointeDay(int number, String pattern) {
        /* 316 */
        java.util.Date date = new java.util.Date();
        /* 317 */
        Calendar calendar = Calendar.getInstance();
        /* 318 */
        calendar.setTime(date);
        /* 319 */
        String formatStr = pattern.toUpperCase();
        String regex1=".*[D]",regex2=".*[M]",regex3=".*[Y]";
        /* 322 */
        if (Pattern.compile(regex1).matcher(formatStr).matches()) {
            /* 323 */
            formatStr = formatStr.replace("D", "d");

            /* 325 */
            calendar.add(5, number);
            /* 326 */
            date = calendar.getTime();
            /* 327 */
            SimpleDateFormat formatter = new SimpleDateFormat(formatStr);
            /* 328 */
            return formatter.format(date);
        }
        /* 329 */
        if (Pattern.compile(regex2).matcher(formatStr).matches()) {
            /* 331 */
            calendar.add(2, number);
            /* 332 */
            date = calendar.getTime();
            /* 333 */
            SimpleDateFormat formatter = new SimpleDateFormat(formatStr);
            /* 334 */
            return formatter.format(date);
        }
        /* 335 */
        if (Pattern.compile(regex3).matcher(formatStr).matches()) {
            /* 337 */
            calendar.add(1, number);
            /* 338 */
            date = calendar.getTime();
            /* 339 */
            SimpleDateFormat formatter = new SimpleDateFormat(formatStr);
            /* 340 */
            return formatter.format(date);
        }
        /* 342 */
        throw new IllegalArgumentException("pattern is error");
    }

    public static synchronized String getLongDayString() {
        /* 352 */
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        /* 353 */
        return sdf.format(new java.util.Date(System.currentTimeMillis()));
    }

    public static synchronized String getDataTimeString(String dataStr) {
        /* 358 */
        String dataTime = "";

        /* 360 */
        String year = dataStr.substring(0, 4);
        /* 361 */
        String month = dataStr.substring(4, 6);
        String day = dataStr.substring(6, 8);

        String hour = dataStr.substring(8, 10);
        String min = dataStr.substring(10, 12);
        String sec = dataStr.substring(12, 14);

        dataTime = year + "-" + month + "-" + day + " " + hour + ":" + min + ":" + sec;

        /* 370 */
        return dataTime;
    }

    public static synchronized String getDateTimeString(String formater) {
        /* 375 */
        SimpleDateFormat sdf = new SimpleDateFormat(formater);
        /* 376 */
        return sdf.format(new java.util.Date(System.currentTimeMillis()));
    }

    public static synchronized String getDateTimeStringforString(java.util.Date date, String formater) {
        /* 381 */
        SimpleDateFormat sdf = new SimpleDateFormat(formater);
        /* 382 */
        return sdf.format(date);
    }

    public static synchronized java.util.Date parseStrToDate(String dateStr) throws Exception {
        /* 388 */
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        /* 389 */
        return df.parse(dateStr);
    }

    public static synchronized String getDateTimeString() {
        /* 393 */
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        /* 394 */
        return sdf.format(new java.util.Date(System.currentTimeMillis()));
    }

    /**
     * 兼容时间不同格式
     *
     * @param dateStr
     * @return
     */
    public static String compatibleTime(String dateStr) {

        String expDateFormat = "";
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        if (StrTools.isEmpty(dateStr)) {
            return expDateFormat;
        }
        // 失效时间兼容不同格式
        if (java.util.regex.Pattern.matches(DATE_TIME_FORMAT_NO_CHANGE, dateStr)) {
            expDateFormat = dateStr;
        }
        else {
            if (java.util.regex.Pattern.matches(DATE_TIME_FORMAT_ONE, dateStr)) {
                LocalDateTime localDateTime = LocalDateTime.parse(dateStr);
                expDateFormat = localDateTime.format(df);
            }
            else if (java.util.regex.Pattern.matches(DATE_TIME_FORMAT_TWO, dateStr)) {
                LocalDateTime localDateTime = LocalDateTime.parse(dateStr);
                expDateFormat = localDateTime.format(df);
            }
        }

        // 时间错误,无法解析，不处理
        return expDateFormat;
    }

    /**
     * 获取当天最大时间
     * @return
     */
    public static Date getEndOfDay() {
        Calendar calendarEnd = Calendar.getInstance();
        calendarEnd.setTime(new Date());
        calendarEnd.set(Calendar.HOUR_OF_DAY, 23);
        calendarEnd.set(Calendar.MINUTE, 59);
        calendarEnd.set(Calendar.SECOND, 59);

        calendarEnd.set(Calendar.MILLISECOND, 0);
        return calendarEnd.getTime();

    }

    /**
     * 获取当前最小时间
     * @return
     */
    public static Date getStartOfDay() {
        LocalDateTime localDateTime = LocalDateTime
            .ofInstant(Instant.ofEpochMilli(System.currentTimeMillis()), ZoneId.systemDefault());
        LocalDateTime startOfDay = localDateTime.with(LocalTime.MIN);
        return Date.from(startOfDay.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 获取当前最小时间
     * @return
     */
    public static String formatTime(Long time) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(time);
        Date date = calendar.getTime();
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//日期格式
        String now = df.format(date);
        return now;
    }

    /**
     * 比较时间，startDate <= 当前时间 <= endDate
     */
    public static boolean compareDate(String startDate, String endDate) {
        if(KiteStringUtils.isBlank(endDate)) {
            return false;
        }
        LocalDate nowDate = LocalDate.now();
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate targetDate = null;
        try {
            targetDate = LocalDate.parse(endDate, dtf);
        } catch (Exception e) {
            return false;
        }
        // endDate 大于等于 当前时间
        boolean flag = !targetDate.isBefore(nowDate);

        // startDate 小于等于 当前时间
        if(flag && KiteStringUtils.isNotBlank(startDate)) {
            try {
                targetDate = LocalDate.parse(startDate, dtf);
            } catch (Exception e) {
                return false;
            }
            flag = !targetDate.isAfter(nowDate);
        }
        return flag;
    }

    public static LocalDate stringToDate(String value) {
        if(KiteStringUtils.isEmpty(value)) {
            return null;
        }
        if(value.length() > DateFormatUtils.DATE_FORMAT.length()) {
            value = value.substring(0, DateFormatUtils.DATE_FORMAT.length());
        }
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern(DateFormatUtils.DATE_FORMAT);
        LocalDate localDate = null;
        try {
            localDate = LocalDate.parse(value, dtf);
        } catch (Exception e) {

        }
        return localDate;
    }
}
